#ifndef TRACTICKETEXPLORERBACKEND_H
#define TRACTICKETEXPLORERBACKEND_H

#include "ticketinterface.h"

#include <QtCore/QObject>
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <QtGui/QStyledItemDelegate>
#include <QtCore/QPointer>
#include <QtCore/QUrl>

namespace XmlRpc {
class XmlRpcConnection;
class XmlRpcResponse;
}

struct TicketField;
class TicketPrivate;

class TracTicketListDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    TracTicketListDelegate(QObject *parent = 0);
    ~TracTicketListDelegate();

    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

struct TracQueryTask {
    int id;
    QPointer<BaseTicketItemModel> model;
};

class TracTicketConfiguration : public ITicketBackendConfiguration
{
    Q_OBJECT
public:
    QString id() const;

    void readSettings(const QSettings &settings);
    void writeSettings(QSettings &settings);

    QUrl url() const { return m_url; }
    QString username() const { return m_username; }
    QString password() const { return m_password; }

private:
    QUrl m_url;
    QString m_username;
    QString m_password;
};

class TracTicketExplorerBackend : public ITicketExplorerBackend
{
    Q_OBJECT
public:
    explicit TracTicketExplorerBackend(ITicketBackendConfiguration *config, QObject *parent = 0);
    ~TracTicketExplorerBackend();

    QString id() const;

    BaseTicketItemModel *queryModel(TicketQuery query);
    QAbstractItemDelegate *listDelegate() const;

    Ticket *createTicket();
    void storeTicket(Ticket *ticket, const QString &comment = "");

    void queryTicket(int ticketId);
    void refreshTicket(Ticket *ticket);

    // These should be in the ticket class
    void loadHistory(Ticket *ticket);
    void loadAvailableActions(Ticket *ticket);

    QList<TicketField> getAvailableFields();

    void updateFields();

    void loadChangedTickets(const QDateTime &since);

    QUrl url() const;
    QString username() const;

private slots:
    void rpcCallComplete(XmlRpc::XmlRpcResponse *response);
    void sendError(const TicketError &err);

private:
    enum RequestType {
        UnknownType,
        ListRequest,
        ListSingleRequest,
        FieldsRequest,
        HistoryRequest,
        ActionsRequest,
        UpdateRequest,
        RecentChangesRequest,
        CreateTicketRequest
    };

    struct TracQuery {
        TracQuery(quint32 id, RequestType rt, Ticket *t)
            : queryId(id), type(rt), ticket(t) {}

        TracQuery() : queryId(0), type(UnknownType), ticket(0) {}

        quint32 queryId;
        RequestType type;
        Ticket *ticket;
    };

    void sendUpdateTicket(TicketPrivate *ticket, const QString &comment = "");
    void sendCreateTicket(TicketPrivate *ticket);
    void doFieldsUpdate(XmlRpc::XmlRpcResponse *response);
    void doHistoryUpdate(const TracQuery &query, XmlRpc::XmlRpcResponse *response);
    void doActionsUpdate(const TracQuery &query, XmlRpc::XmlRpcResponse *response);

    Ticket *ticketFromVariant(const QVariant &val);
    bool updateTicketFromVariant(Ticket *ticket, const QVariant &val);

    XmlRpc::XmlRpcConnection *m_con;
    quint32 m_queryId;
    QMap<XmlRpc::XmlRpcResponse *, TracQuery> m_requests;
    QPointer<BaseTicketItemModel> m_queryModel;
    int m_ticketQueryCount;
    int m_totalTickets;

    QList<TicketField> m_ticketFields;
};

#endif // TRACTICKETEXPLORERBACKEND_H
